#include "util.h"
#include "SpriteTile.h"
#include "GraphicFactory.h"

namespace Graphics
{
	SpriteTile::SpriteTile(DWORD col,DWORD row,Drawable* image,TILE_BASE base):
			m_TileBase(base),m_pSize(new Core::Size(0,0))
	{
		if(col == 0)
		{
			col = 1;
		}
		if(row == 0)
		{
			row = 1;
		}
		if(m_TileBase == BASE_SIZE)
		{
			m_TileW = (float)col;
			m_TileH = (float)row;
			m_TileWZ = m_TileW * this->GetZoomX();
			m_TileHZ = m_TileH * this->GetZoomY();
		}
		else // BASE_COUNT
		{
			m_Col = col;
			m_Row = row;
		}
		this->SetImage(image);
	}
	SpriteTile::~SpriteTile(void)
	{
		delete m_pSize;
	}
	bool SpriteTile::RenderImpl(void)
	{
		Viewport* pVP = this->GetViewport();
		if(pVP == 0)
		{
			return false;
		}

		const TileData& tile = this->GetData();	
		if(this->GetImage() == NULL || tile.count <= 0)
		{
			return false;
		}


		Graphic2D* const g = GraphicFactory::getInstance()->GetGraphic2D();
		Position p = this->GetPos();
		p.x += pVP->GetRenderRect().left;
		p.y += pVP->GetRenderRect().top;

		bool result = true;

		// counter
		DWORD k = 0;

		int dx = p.x;
		int dy = p.y;

		m_pSize->height = 0;
		m_pSize->width = 0;
		for(DWORD i = 0;k < tile.count; i++)
		{
			for(DWORD j = 0; j < tile.width; j++)
			{
				DWORD id = tile.pData[k];
				
				DWORD y = id / m_Col;
				DWORD x = id % m_Col;

				Rect sr((int)(x * m_TileW),(int)(y * m_TileH),
						(int)(x * m_TileW + m_TileW),(int)(y * m_TileH + m_TileH));

				Rect dr(dx,dy, dx + (int)m_TileWZ ,dy + (int)m_TileHZ);
				
				sr.ClipRect(pVP->GetRenderRect(),dr);

				result &= g->Blt(this->GetImage(),&sr,&dr,&this->GetInfo());
				k++;
				if(k >= tile.count)
				{
					break;
				}
				if(tile.pStep != NULL)
				{
					dx += (int)(m_TileWZ * tile.pStep[k]);
				}else
				{
					dx += (int)m_TileWZ;
				}
			}
			if(dx + (int)m_TileWZ - p.x > m_pSize->width)
			{
				m_pSize->width = dx + (int)m_TileWZ - p.x;
			}
			dx = p.x;
			dy += (int)m_TileHZ;
		}
		m_pSize->height = dy - p.y;
		return result;
	}
	
	void SpriteTile::SetImage(Drawable* image)
	{
		Sprite::SetImage(image);
		if( image != 0)
		{
			if(m_TileBase == BASE_SIZE)
			{
				m_Col = this->GetImage()->GetWidth() / (DWORD)m_TileW;
				m_Row = this->GetImage()->GetHeight() / (DWORD)m_TileH;
			}
			else // BASE_COUNT
			{
				m_TileW = this->GetImage()->GetWidth()/(float)m_Col;
				m_TileH = this->GetImage()->GetHeight()/(float)m_Row;
				m_TileWZ = m_TileW * this->GetZoomX();
				m_TileHZ = m_TileH * this->GetZoomY();
			}
		}
	}

	void SpriteTile::SetZoomX(float zx)
	{
		Sprite::SetZoomX(zx);
		m_TileWZ = m_TileW * this->GetZoomX();
	}

	void SpriteTile::SetZoomY(float zy)
	{
		Sprite::SetZoomY(zy);
		m_TileHZ = m_TileH * this->GetZoomY();
	}

	DWORD SpriteTile::GetCol(void)
	{
		return m_Col;
	}
	DWORD SpriteTile::GetRow(void)
	{
		return m_Row;
	}
	TILE_BASE SpriteTile::GetTileBase(void)
	{
		return m_TileBase;
	}
	const Core::Size& SpriteTile::GetSize(void)
	{
		return *m_pSize;
	}
}
